!! Copyright (C) 2009,2010,2011,2012  Marco Restelli
!!
!! This file is part of:
!!   LDGH -- Local Hybridizable Discontinuous Galerkin toolkit
!!
!! LDGH is free software: you can redistribute it and/or modify it
!! under the terms of the GNU General Public License as published by
!! the Free Software Foundation, either version 3 of the License, or
!! (at your option) any later version.
!!
!! LDGH is distributed in the hope that it will be useful, but WITHOUT
!! ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
!! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
!! License for more details.
!!
!! You should have received a copy of the GNU General Public License
!! along with LDGH. If not, see <http://www.gnu.org/licenses/>.
!!
!! author: Marco Restelli                   <marco.restelli@gmail.com>


!>\brief
!!
!! Common interface of the time integrators
!!
!! \n
!!
!! This module simply provides a unified interface to all the time
!! integrators. The specific constructors and destructors are callend in this module.
!<----------------------------------------------------------------------
module mod_time_integrators

!-----------------------------------------------------------------------

 use mod_messages, only: &
   mod_messages_initialized, &
   error,   &
   warning, &
   info

 use mod_kinds, only: &
   mod_kinds_initialized, &
   wp

 use mod_time_integrators_base, only: &
   mod_time_integrators_base_constructor, &
   mod_time_integrators_base_destructor,  &
   c_ode

 use mod_rk, only: &
   mod_rk_constructor, &
   mod_rk_destructor,  &
   ee_init,      ee_step,      ee_clean,      &
   hm_init,      hm_step,      hm_clean,      &
   ssprk54_init, ssprk54_step, ssprk54_clean

 use mod_multistep, only: &
   mod_multistep_constructor, &
   mod_multistep_destructor,  &
   thetam_init, thetam_step, thetam_clean, &
   bdf1_init,   bdf1_step,   bdf1_clean,   &
   bdf2_init,   bdf2_step,   bdf2_clean,   &
   bdf3_init,   bdf3_step,   bdf3_clean,   &
   bdf2ex_init, bdf2ex_step, bdf2ex_clean

!-----------------------------------------------------------------------
 
 implicit none

!-----------------------------------------------------------------------

! Module interface

 public :: &
   mod_time_integrators_constructor, &
   mod_time_integrators_destructor,  &
   mod_time_integrators_initialized, &
   c_ode,                                     &
   ee_init,      ee_step,      ee_clean,      &
   hm_init,      hm_step,      hm_clean,      &
   ssprk54_init, ssprk54_step, ssprk54_clean, &
   thetam_init,  thetam_step,  thetam_clean,  &
   bdf1_init,    bdf1_step,    bdf1_clean,    &
   bdf2_init,    bdf2_step,    bdf2_clean,    &
   bdf3_init,    bdf3_step,    bdf3_clean,    &
   bdf2ex_init,  bdf2ex_step,  bdf2ex_clean

 private

!-----------------------------------------------------------------------

! Module types and parameters

! Module variables

 ! public members
 logical, protected ::               &
   mod_time_integrators_initialized = .false.
 ! private members
 character(len=*), parameter :: &
   this_mod_name = 'mod_time_integrators'

!-----------------------------------------------------------------------

contains

!-----------------------------------------------------------------------

 subroutine mod_time_integrators_constructor()
  character(len=*), parameter :: &
    this_sub_name = 'constructor'

   !Consistency checks ---------------------------
   if( (mod_messages_initialized.eqv..false.) .or. &
       (mod_kinds_initialized   .eqv..false.) ) then
     call error(this_sub_name,this_mod_name, &
                'Not all the required modules are initialized.')
   endif
   if(mod_time_integrators_initialized.eqv..true.) then
     call warning(this_sub_name,this_mod_name, &
                  'Module is already initialized.')
   endif
   !----------------------------------------------

   call mod_time_integrators_base_constructor()
   call mod_rk_constructor()
   call mod_multistep_constructor()

   mod_time_integrators_initialized = .true.
 end subroutine mod_time_integrators_constructor

!-----------------------------------------------------------------------
 
 subroutine mod_time_integrators_destructor()
  character(len=*), parameter :: &
    this_sub_name = 'destructor'
   
   !Consistency checks ---------------------------
   if(mod_time_integrators_initialized.eqv..false.) then
     call error(this_sub_name,this_mod_name, &
                'This module is not initialized.')
   endif
   !----------------------------------------------

   call mod_multistep_destructor()
   call mod_rk_destructor()
   call mod_time_integrators_base_destructor()

   mod_time_integrators_initialized = .false.
 end subroutine mod_time_integrators_destructor

!-----------------------------------------------------------------------

end module mod_time_integrators

